namespace classifier_test
{

namespace vem
{

using namespace high_order;

class vem_concept_cutter : public concept_cutter
{
public:
	vem_concept_cutter();
	vem_concept_cutter(const vem_concept_cutter& Val);
	smart_ptr<concept_cutter> clone() const;
	void serialize(serializer& Serializer);
	void initialize_options(command_line_options& Options) const;
	void apply_arguments(const command_line_arguments& Args);
	void set_base_block_size(int Val);
	void set_move_offset(double Val);
	void set_amplification(double Val);
	void set_prune(bool Val);

	void compute();
	int get_chunk_count() const;
	const chunk& get_chunk(int I) const;
	double compute_estimated_validation_error() const;

private:
	struct level
	{
		int size;
		int offset;
	};
	struct block
	{
		smart_ptr<validation_classifier> vclassifier;
		smart_ptr<classifier> ensemble_classifier;
		double verror;
	};

	int BaseBlockSize;
	double MoveOffset;
	double Amplification;
	bool Prune;
	vector<level> Levels;
	vector<vector<block> > Blocks;
	vector<double> BestErrors;
	vector<int> BestCuts;
	vector<chunk> Chunks;
	double EstVError;

	void init_levels();
	void init_blocks();
	void find_best_cuts();
	void find_chunks();

	void make_block(block& Block, int Begin, int End);
	bool good_block(int End, int Lev);
	int left_bound_of_block(int End, int Lev);
};

}

}
